package eu.webhib.frmwrk.service.impl;

import eu.webhib.frmwrk.domain.intf.ParentChildEntity;
import eu.webhib.frmwrk.persistence.PersistenceMngr;
import eu.webhib.frmwrk.service.intf.ParentChildService;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * Service implementation for managing the persistence state of entities with parent/child relationship
 * @param <T> type of parent/child related entity managed by this service
 */
public class ParentChildServiceImpl<T extends ParentChildEntity<T>>
        extends BaseServiceImpl<T> implements ParentChildService<T> {

   private static final Logger log = Logger.getLogger(ParentChildServiceImpl.class);

   @Override
   public void save(T entity) {
      log.debug("save: " + entity.getClass().getSimpleName());

      /** if parent is set and is not persistent in this persistence context */
      if (entity.getParent() != null) {
         if (!PersistenceMngr.getEntityManager().contains(entity.getParent())) {
            /** read the persistent entity from this transaction,
             *  e.g. needed for new entered entities having a detached parent assigned */
            entity.setParent(findId(entity.getParent().getId()));
         }
      }
      super.save(entity);
   }

   @Override
   public List<T> getRootList() {
      log.debug("getRootList");

      return getRootListByAllQuery();

      // persistent variant
      //return findByAttribute("parent", null); TODO persistent child getRootList
   }

   /* todo: remove */
   @Override
   public void moveToNewParent(T entityToChange, T newParent) {
      log.debug("moveToNewParent");
      /*
      entityToChange.setParent(newParent);
      update(entityToChange);*/
   }
    

   private List<T> getRootListByAllQuery() {

      List<T> allEntities = findByNamedQuerySuffix("_AllOrdered");

      log.trace("getRootListByAllQuery: allEntities " + allEntities.size());
      /** need to clear the collections if method is called twice for the same EntityManager */
      for (T entry : allEntities) {
         entry.clearChildren();
      }
      List<T> rootList = new ArrayList<T>(50);
      for (T entry : allEntities) {
         if (entry.getParent() == null) {
            /** is top level entity so add to root list */
            rootList.add(entry);
         } else {
            /** wire into the children list */
            entry.getParent().getChildren().add(entry);
         }
      }
      log.trace("getRootListByAllQuery: rootList " + rootList.size());
      return rootList;
   }
}
